bitkeeper revision 1.1143 (4110b5c38VYeFSdv3JdFEuUgJgQXcg)
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Wed, 4 Aug 2004 10:09:07 +0000 (10:09 +0000)
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Wed, 4 Aug 2004 10:09:07 +0000 (10:09 +0000)
Add a HYPERVISOR_vm_assist() hypercall for optionally enabling features
such as writeable pagetables.

linux-2.6.7-xen-sparse/arch/xen/i386/kernel/setup.c
linux-2.6.7-xen-sparse/include/asm-xen/hypervisor.h
xen/arch/x86/traps.c
xen/arch/x86/x86_32/emulate.c
xen/arch/x86/x86_32/entry.S
xen/common/kernel.c
xen/include/hypervisor-ifs/hypervisor-if.h
xen/include/xen/sched.h

index 6872e4278bbb8cc24a91d202a70aa7d68fd63600..e2fea04403eeb76b60c7035f3c8c4c737ee65440 100644 (file)
@@ -1096,6 +1096,13 @@ void __init setup_arch(char **cmdline_p)
 {
        unsigned long max_low_pfn;
 
+       HYPERVISOR_vm_assist(VMASST_CMD_enable,
+                            VMASST_TYPE_4gb_segments);
+#if 0
+       HYPERVISOR_vm_assist(VMASST_CMD_enable,
+                            VMASST_TYPE_writeable_pagetables);
+#endif
+
        memcpy(&boot_cpu_data, &new_cpu_data, sizeof(new_cpu_data));
        early_cpu_init();
 
index 9909a2c466b493c51107a6097c308c19bb53b253..5b89913a811ef52234b6c755d53525585e6711e2 100644 (file)
@@ -467,4 +467,15 @@ static inline int HYPERVISOR_update_va_mapping_otherdomain(
     return ret;
 }
 
+static inline int HYPERVISOR_vm_assist(unsigned int cmd, unsigned int type)
+{
+    int ret;
+    __asm__ __volatile__ (
+        TRAP_INSTR
+        : "=a" (ret) : "0" (__HYPERVISOR_vm_assist),
+        "b" (cmd), "c" (type) : "memory" );
+
+    return ret;
+}
+
 #endif /* __HYPERVISOR_H__ */
index b40c8d198c51a7ec4a9a51e989e6e74742e7e56f..7551d17260384feced65e92e6496f470a8424ff9 100644 (file)
@@ -310,50 +310,54 @@ asmlinkage void do_page_fault(struct pt_regs *regs, long error_code)
     struct guest_trap_bounce *gtb = guest_trap_bounce+smp_processor_id();
     trap_info_t *ti;
     unsigned long off, addr, fixup;
-    struct domain *p = current;
+    struct domain *d = current;
     extern int map_ldt_shadow_page(unsigned int);
-    int cpu = smp_processor_id();
+    int cpu = d->processor;
 
     __asm__ __volatile__ ("movl %%cr2,%0" : "=r" (addr) : );
 
     perfc_incrc(page_faults);
 
     if ( unlikely(addr >= LDT_VIRT_START) && 
-         (addr < (LDT_VIRT_START + (p->mm.ldt_ents*LDT_ENTRY_SIZE))) )
+         (addr < (LDT_VIRT_START + (d->mm.ldt_ents*LDT_ENTRY_SIZE))) )
     {
         /*
          * Copy a mapping from the guest's LDT, if it is valid. Otherwise we
          * send the fault up to the guest OS to be handled.
          */
         off  = addr - LDT_VIRT_START;
-        addr = p->mm.ldt_base + off;
+        addr = d->mm.ldt_base + off;
         if ( likely(map_ldt_shadow_page(off >> PAGE_SHIFT)) )
             return; /* successfully copied the mapping */
     }
 
-    if ((addr >> L2_PAGETABLE_SHIFT) == ptwr_info[cpu].disconnected) {
+    if ( (addr >> L2_PAGETABLE_SHIFT) == ptwr_info[cpu].disconnected )
+    {
         ptwr_reconnect_disconnected(addr);
         return;
     }
 
-    if (addr < PAGE_OFFSET && error_code & 2 && ptwr_do_page_fault(addr))
+    if ( VM_ASSIST(d, VMASST_TYPE_writeable_pagetables) && 
+         (addr < PAGE_OFFSET) &&
+         ((error_code & 3) == 3) && /* write-protection fault */
+         ptwr_do_page_fault(addr) )
         return;
 
-    if ( unlikely(p->mm.shadow_mode) && 
+    if ( unlikely(d->mm.shadow_mode) && 
          (addr < PAGE_OFFSET) && shadow_fault(addr, error_code) )
         return; /* Returns TRUE if fault was handled. */
 
     if ( unlikely(!(regs->xcs & 3)) )
         goto xen_fault;
 
-    ti = p->thread.traps + 14;
+    ti = d->thread.traps + 14;
     gtb->flags = GTBF_TRAP_CR2; /* page fault pushes %cr2 */
     gtb->cr2        = addr;
     gtb->error_code = error_code;
     gtb->cs         = ti->cs;
     gtb->eip        = ti->address;
     if ( TI_GET_IF(ti) )
-        p->shared_info->vcpu_data[0].evtchn_upcall_mask = 1;
+        d->shared_info->vcpu_data[0].evtchn_upcall_mask = 1;
     return; 
 
  xen_fault:
@@ -361,7 +365,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, long error_code)
     if ( likely((fixup = search_exception_table(regs->eip)) != 0) )
     {
         perfc_incrc(copy_user_faults);
-        if ( !p->mm.shadow_mode )
+        if ( !d->mm.shadow_mode )
             DPRINTK("Page fault: %08lx -> %08lx\n", regs->eip, fixup);
         regs->eip = fixup;
         regs->xds = regs->xes = regs->xfs = regs->xgs = __HYPERVISOR_DS;
@@ -405,7 +409,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, long error_code)
 
 asmlinkage void do_general_protection(struct pt_regs *regs, long error_code)
 {
-    struct domain *p = current;
+    struct domain *d = current;
     struct guest_trap_bounce *gtb = guest_trap_bounce+smp_processor_id();
     trap_info_t *ti;
     unsigned long fixup;
@@ -457,7 +461,9 @@ asmlinkage void do_general_protection(struct pt_regs *regs, long error_code)
     }
 
 #if defined(__i386__)
-    if ( (error_code == 0) && gpf_emulate_4gb(regs) )
+    if ( VM_ASSIST(d, VMASST_TYPE_4gb_segments) && 
+         (error_code == 0) && 
+         gpf_emulate_4gb(regs) )
         return;
 #endif
     
@@ -469,7 +475,7 @@ asmlinkage void do_general_protection(struct pt_regs *regs, long error_code)
     gtb->cs         = ti->cs;
     gtb->eip        = ti->address;
     if ( TI_GET_IF(ti) )
-        p->shared_info->vcpu_data[0].evtchn_upcall_mask = 1;
+        d->shared_info->vcpu_data[0].evtchn_upcall_mask = 1;
     return;
 
  gp_in_kernel:
index 08fb036cc09b57ef2cbc566c694f4bc66db297ca..aac7aa071d878195b2ac40ae9960cdac3edf873f 100644 (file)
@@ -499,31 +499,6 @@ int gpf_emulate_4gb(struct pt_regs *regs)
         goto undecodeable;
     }
 
-#if 0
-    {
-        char str1[] = { 0x65,0x8b,0x00,0x8b,0x30 };
-        char str2[] = { 0x65,0x8b,0x02,0x8b,0x40,0x0c };
-        char str3[] = { 0x65,0x8b,0x30,0x85,0xf6 };
-        char str4[] = { 0x65,0x8b,0x00,0x5d,0x8b,0x00 };
-        char str5[] = { 0x65,0x89,0x30,0x8b,0x45,0x08 };
-        char str6[] = { 0x65,0x8b,0x00,0x8b,0x50,0x0c };
-        char str7[] = { 0x65,0x89,0x51,0x00,0x83,0xc8,0xff };
-        if ( (memcmp(eip,str1,5) == 0) ||
-             (memcmp(eip,str2,6) == 0) ) goto out;
-        if ( (memcmp(eip,str3,5) == 0) ||
-             (memcmp(eip,str4,6) == 0) ) goto out;
-        if ( (memcmp(eip,str5,6) == 0) ||
-             (memcmp(eip,str6,6) == 0) ) goto out;
-        if ( (memcmp(eip,str7,7) == 0) ||
-             (memcmp(eip,str7,7) == 0) ) goto out;
-    }
-    printk(" .byte 0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x\n",
-           eip[-8],eip[-7],eip[-6],eip[-5],eip[-4],eip[-3],eip[-2],eip[-1]);
-    printk(" .byte 0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x\n",
-           eip[0],eip[1],eip[2],eip[3],eip[4],eip[5],eip[6],eip[7]);
-    printk(" @ %04x:%08lx\n", regs->xcs, regs->eip);
-#endif
-
     /* Success! */
     perfc_incrc(emulations);
     regs->eip += pb - eip;
index fbd33eb73baf985ba56a501fa3484ebdb169350a..2c07d8cc5b97986ea02adf54134917bc4ec61f35 100644 (file)
@@ -719,6 +719,7 @@ ENTRY(hypercall_table)
         .long SYMBOL_NAME(do_console_io)
         .long SYMBOL_NAME(do_physdev_op)
         .long SYMBOL_NAME(do_update_va_mapping_otherdomain) /* 20 */
+        .long SYMBOL_NAME(do_vm_assist)
         .rept NR_hypercalls-((.-hypercall_table)/4)
         .long SYMBOL_NAME(do_ni_hypercall)
         .endr
index 9d6d6e92f795f28cac077304f986190718bf3599..de9e1c26c9948ec714cc0caca4db7aab939eb9f9 100644 (file)
@@ -340,6 +340,24 @@ long do_xen_version(int cmd)
     return (XEN_VERSION<<16) | (XEN_SUBVERSION);
 }
 
+long do_vm_assist(unsigned int cmd, unsigned int type)
+{
+    if ( type > (sizeof(unsigned long) * 8) )
+        return -EINVAL;
+
+    switch ( cmd )
+    {
+    case VMASST_CMD_enable:
+        set_bit(type, &current->vm_assist);
+        return 0;
+    case VMASST_CMD_disable:
+        clear_bit(type, &current->vm_assist);
+        return 0;
+    }
+
+    return -ENOSYS;
+}
+
 long do_ni_hypercall(void)
 {
     /* No-op hypercall. */
index 724213acae5390cd9d4176062d922374233c76da..1c9aef8f5381e51d9f32a317ae76cc4b3016e534 100644 (file)
@@ -44,6 +44,7 @@
 #define __HYPERVISOR_console_io           18
 #define __HYPERVISOR_physdev_op           19
 #define __HYPERVISOR_update_va_mapping_otherdomain 20
+#define __HYPERVISOR_vm_assist            21
 
 /*
  * MULTICALLS
 #define MEMOP_increase_reservation 0
 #define MEMOP_decrease_reservation 1
 
+/*
+ * Commands to HYPERVISOR_vm_assist().
+ */
+#define VMASST_CMD_enable                0
+#define VMASST_CMD_disable               1
+#define VMASST_TYPE_4gb_segments         0
+#define VMASST_TYPE_writeable_pagetables 1
+
 #ifndef __ASSEMBLY__
 
 typedef u32 domid_t;
index f8175fda83df043123f3b2b7c6ae8fdafa2b0f55..ef68c443a047f6bb6709c2eba9c2ebc97edd4235 100644 (file)
@@ -144,6 +144,7 @@ struct domain
     unsigned long *io_bitmap; /* Pointer to task's IO bitmap or NULL */
 
     unsigned long flags;
+    unsigned long vm_assist;
 
     atomic_t refcnt;
     atomic_t pausecnt;
@@ -289,6 +290,8 @@ static inline void domain_unpause_by_systemcontroller(struct domain *d)
 #define IS_PRIV(_d) (test_bit(DF_PRIVILEGED, &(_d)->flags))
 #define IS_CAPABLE_PHYSDEV(_d) (test_bit(DF_PHYSDEV, &(_d)->flags))
 
+#define VM_ASSIST(_d,_t) (test_bit((_t), &(_d)->vm_assist))
+
 #include <xen/slab.h>
 #include <asm/domain.h>